#pragma once
#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>

class Request
{
public:
    Request(int x = 0,int y = 0,char oper = 0):_x(x),_y(y),_oper(oper)
    {}
    
    bool Serialize(std::string* out)
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;
        Json::StyledWriter writer;
        *out = writer.write(root);
        return !out->empty();
    }

    bool DeSerialize(const std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret = reader.parse(in,root);
        if(!ret)
            return false;
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }
    
    int X()
    {
        return _x;
    }

    int Y()
    {
        return _y;
    }

    char Oper()
    {
        return _oper;
    }
private:
    int _x;
    int _y;
    char _oper;
};

class Response
{
public:
    Response():_result(0),_code(0)
    {}

    bool Serialize(std::string* out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::StyledWriter writer;
        *out = writer.write(root);
        return !out->empty();
    }

    bool DeSerialize(const std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ret = reader.parse(in,root);
        if(!ret)
            return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        return true;
    }

    void SetCode(int code)
    {
        _code = code;
    }

    void SetResult(int result)
    {
        _result = result;
    }

    int Result()
    {
        return _result;
    }

    int Code()
    {
        return _code;
    }
    void Print()
    {
        std::cout << "[" << _code << "]" << _result << std::endl;
    }
private:
    int _result;//运算结果
    int _code;//运算结果是否可信，1表示可信，0表示不可信
};


const std::string sep = "\r\n";
class Package
{
    public:
    //将已经序列化好的字符串进行打包
    static bool Pack(std::string& str)
    {
        std::string len = std::to_string(str.size()) + sep;
        str.insert(0,len);
        str += sep;
        return true;
    }

    //将打包好的字符串解包，变为纯json串
    //有可能传输过来的字符串并不是完整的
    //str是目前传过来的打包好的串，out是希望带出的纯json串
    static bool Unpack(std::string& str,std::string* out)
    {
        int pos = str.find(sep);//首先第一个分隔符：找长度
        if(pos == std::string::npos)
            return false;
        std::string len = str.substr(0,pos);//拿到有效载荷长度
        
        int length = std::stoi(len) + len.size() + 2 * sep.size();//通过有效载荷长度，2各分隔符长度，以及长度自身，可以计算出一个打包好的完整报文长度
        if(str.size() < length)
            return false;//说明未接收完全
        //接收完全
        *out = str.substr(pos + sep.size(),stoi(len));//拿到纯json串
        str.erase(0,length);
        return true;
    }
};
